//
//  HJJSONResponseSerializer.m
//  KaiChat
//
//  Created by lx on 2023/12/5.
//

#import "HJJSONResponseSerializer.h"
#import "HJCryptoTool.h"


static NSError * HJErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
    if (!error) {
        return underlyingError;
    }

    if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
        return error;
    }

    NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
    mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;

    return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
}

static BOOL HJErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
    if ([error.domain isEqualToString:domain] && error.code == code) {
        return YES;
    } else if (error.userInfo[NSUnderlyingErrorKey]) {
        return HJErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
    }

    return NO;
}

id HJJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
    
#ifdef DEBUG
    return JSONObject;
#else
    if ([JSONObject isKindOfClass:[NSArray class]]) {
        NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
        for (id value in (NSArray *)JSONObject) {
            if (![value isEqual:[NSNull null]]) {
                [mutableArray addObject:HJJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
            }
        }

        return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
    } else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
        NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
        for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
            id value = (NSDictionary *)JSONObject[key];
            if (!value || [value isEqual:[NSNull null]]) {
                [mutableDictionary removeObjectForKey:key];
            } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
                mutableDictionary[key] = HJJSONObjectByRemovingKeysWithNullValues(value, readingOptions);
            }
        }

        return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
    }
    return JSONObject;

#endif

}

@implementation HJJSONResponseSerializer

- (id)responseObjectForResponse:(NSURLResponse *)response
                           data:(NSData *)data
                          error:(NSError *__autoreleasing *)error
{
    
    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
        if (!error || HJErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
            return nil;
        }
    }
 
    BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
    
    if (data.length == 0 || isSpace) {
        return nil;
    }
    
    NSHTTPURLResponse *HTTPURLResponse = (NSHTTPURLResponse *)response;
    NSString *iv = HTTPURLResponse.allHeaderFields[@"Key"];
 
    HJAppEnvType appEnvType = getAppEnvType();
    BOOL isCrypto = isUseCrypto() || ((appEnvType == HJAppEnvTypePro || appEnvType == HJAppEnvTypePre) && [response.URL.path containsString:@"wallet"]);
    if (isCrypto && !isEmptyString(iv) && [response.URL.absoluteString hasPrefix:getBaseUrlString()]) {
        
        NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSString *decryptString = [HJCryptoTool decryptString:responseString iv:iv];
        
        id responseObject = [decryptString mj_JSONObject];

        if (!responseObject)
        {
            if (error) {
                *error = HJErrorWithUnderlyingError([NSError errorWithCode:-100111 errorReason:@"Decryption failed"], *error);
            }
            return nil;
        }
        TJLog(@"解密成功");
        return HJJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
    }

    NSError *serializationError = nil;
    
    id responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
    if (!responseObject)
    {
        if (error) {
            *error = HJErrorWithUnderlyingError(serializationError, *error);
        }
        return nil;
    }
    return HJJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
}

@end
